//
// Mouse Gesture Recognizer
// (c) Robert Hahn / HTW Dresden
//
// GestureRecognizer.cs
// --------------------
// The main recognizer class which contains a neural network, the draw logic
// and the recorded patterns.
// The constructor will connect the required events with the parent control.
//
// The serialization is done by the serialization constructor and the 
// GetObjectData method.

using System;
using System.IO;
using System.Collections;
using System.ComponentModel;

using System.Runtime.Serialization;
//using System.Runtime.Serialization.Formatters.Soap;
using System.Runtime.Serialization.Formatters.Binary;
using System.Diagnostics;

using CStock;



namespace CNeural
{
	/// <summary>
	/// The gesture recognizer records mouse gestures and trains a neural 
	/// network to recognize them.
	/// </summary>
	[Serializable]
	public class TestNeuronalNetwork : ISerializable, IDisposable
	{
		#region Fields



		protected bool             isDisposed = false;
		protected int              updateInterval;	

		protected NetworkBackPropagation network;
		

		#endregion
		
		#region Contructors
		IProgramContext programContext;
		string resultString;
		

		public TestNeuronalNetwork(IProgramContext dh):this()
		{
			
			this.programContext = dh;
			this.resultString = string.Empty;
		
			NNSimple nn = new NNSimple();
			nn.NumberNodeInput = 2;
			nn.NumberNodesHidden = 2;    
			nn.NumberNodesOutput = 1;    
			nn.NumberPatterns = 4;    
			nn.Test();
		
		}
	
		/// <summary>
		/// Constructs a new gesture recognizer.
		/// </summary>
		public TestNeuronalNetwork()
		{
			
	
		}		
		/// <summary>
		/// Disconnects the event handler from the parent control.
		/// </summary>
		public void Dispose()
		{
			if (!this.isDisposed)
			{
				this.network.LearningFinished -= new EventHandler(OnLearningFinished);
				this.network.StepFinished -= new EventHandler(OnStepFinished);				
				
				
	
				System.GC.SuppressFinalize(this);
				this.isDisposed = true;
			}
		}

		/// <summary>
		/// Destructor.
		/// </summary>
		~TestNeuronalNetwork()
		{
		
		}		
		#endregion

		#region Properties
	
	

		/// <summary>
		/// Gets or sets the neural network used for learning.
		/// </summary>
		[Description("The neural network which is used for pattern recognizing.")]
		[Category("Data")]
		public NetworkBackPropagation NetworkNeural 
		{
			get
			{ 
				return this.network; 
			}
			set 
			{ 
				this.network = value; 
			}
		}


		#endregion

		#region Methods
	

		private void CreateLearnPatterns()
		{
			NeuralPatternList trainingPatterns = new NeuralPatternList();
			
			ArrayList inp;
			ArrayList outp ;
			NeuralPattern sp;

			inp = new ArrayList();
			inp.Add(0.0);
			inp.Add(0.0);
			outp = new ArrayList();
			outp.Add(0.0);

			sp = new NeuralPattern(inp,outp);
			trainingPatterns.Add(sp);

			inp = new ArrayList();
			inp.Add(0.0);
			inp.Add(1.0);
			outp = new ArrayList();
			outp.Add(1.0);
			sp = new NeuralPattern(inp,outp);
			trainingPatterns.Add(sp);

			inp = new ArrayList();
			inp.Add(1.0);
			inp.Add(0.0);
			outp = new ArrayList();
			outp.Add(1.0);
			sp = new NeuralPattern(inp,outp);
			trainingPatterns.Add(sp);

			inp = new ArrayList();
			inp.Add(1.0);
			inp.Add(1.0);
			outp = new ArrayList();
			outp.Add(1.0);
			sp = new NeuralPattern(inp,outp);
			trainingPatterns.Add(sp);

			//-------------------------------
			//training	
			this.network.TrainingPatterns = trainingPatterns;
		}
		/// <summary>
		/// Trains the neural network using the known gestures as input 
		/// patterns.
		/// </summary>
		public void TrainNetworkNeural() 
		{
			// init the neural network
			this.network = new NetworkBackPropagation();
			this.network.LearningFinished += new EventHandler(OnLearningFinished);
			this.network.StepFinished += new EventHandler(OnStepFinished);


			this.network.NumberOfHiddenLayers = 1;
			this.network.InitializeNewNetwork(2,2,1);
			this.network.ErrorLimit = 0.0001F;
			this.network.Momentum = 0.9F;
			this.network.LearnRate = 0.5F;
			this.network.MaximumIterations = 10000;
			this.network.Connect();


			CreateLearnPatterns();
			this.network.TrainNetwork();

			//-----------------------------
			//train results in the method
		}

		public void SimulateTest()
		{
			ArrayList inp;
			ArrayList outp ;
			NeuralPattern sp;
			//-----------------------------------
			//simulation
			inp = new ArrayList();
			inp.Add(0.0);
			inp.Add(0.0);
			outp = new ArrayList();
			outp.Add(0.0);
			sp = new NeuralPattern(inp,outp);

			this.network.SimulateNetwork(sp);
			ArrayList arr = this.network.GetSimulationResults();
			for(int i = 0; i < arr.Count; i++)
			{
				Debug.WriteLine("SimulationResults " + arr[i].ToString());
			}
		}

		/// <summary>
		/// Stops the learning thread.
		/// </summary>
		public void StopTraining()
		{
			this.NetworkNeural.IsLearning = false;
		}


		/// <summary>
		/// Relays the learining finished event of the neural network.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void OnLearningFinished(object sender, EventArgs e) 
		{
			Debug.WriteLine("Training finished.", "Information");
			
			ArrayList arr = this.network.GetTrainingResults();
			Debug.WriteLine("TrainingIterations " + this.network.LearnIterations.ToString());

			for(int i = 0; i < arr.Count; i++)
			{
				//Debug.WriteLine("TrainingResults " + arr[i].ToString());
			}


		}


		/// <summary>
		/// Relays the learning step finished event of the neural network.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void OnStepFinished(object sender, EventArgs e) 
		{
			//perhaps implement later !

		}
		
	
		
		#endregion

		#region serialization

		public void GetObjectData(SerializationInfo info, 
			StreamingContext context)
		{
			info.AddValue("NetworkNeural", this.network);
			info.AddValue("UpdateInterval", this.updateInterval);
		}
		
			
		/// <summary>
		/// Deserializes a gesture recognizer from a file.
		/// </summary>
		/// <param name="filename">The filename of the file to load.</param>
		/// <returns>A new gesture recognizer object containing the file content.</returns>
		public static TestNeuronalNetwork Load(string filename)
		{
			FileStream fs = new FileStream(filename, FileMode.Open);
			// SoapFormatter formatter = new SoapFormatter();
			BinaryFormatter formatter = new BinaryFormatter();
			return (TestNeuronalNetwork) formatter.Deserialize(fs);
		}


		/// <summary>
		/// Deserializes a gesture recognizer from an open stream.
		/// </summary>
		/// <param name="stream">The stream to load the gesture list from.</param>
		/// <returns>A new gesture gesture recognizer object containing the stream content.</returns>
		public static TestNeuronalNetwork Load(Stream stream)
		{
			// SoapFormatter formatter = new SoapFormatter();
			BinaryFormatter formatter = new BinaryFormatter();
			return (TestNeuronalNetwork) formatter.Deserialize(stream);
		}	
		/// <summary>
		/// Serializes the object to a file.
		/// </summary>
		/// <param name="filename"></param>
		public void Save(string filename)
		{
			FileStream fs = new FileStream(filename, FileMode.Create);
			//SoapFormatter formatter = new SoapFormatter();
			BinaryFormatter formatter = new BinaryFormatter();
			formatter.Serialize(fs, this);
		}


		/// <summary>
		/// Serializes the object to a stream.
		/// </summary>
		/// <param name="stream">The stream which is used for saving.</param>
		public void Save(Stream stream) 
		{
			// SoapFormatter formatter = new SoapFormatter();
			BinaryFormatter formatter = new BinaryFormatter();
			formatter.Serialize(stream, this);
		}
		

	
		#endregion

	}


}
